package indi.zjh.dp.orm;

import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.dom4j.DocumentException;

import com.mysql.fabric.xmlrpc.base.Data;
import com.mysql.jdbc.MysqlDataTruncation;
import com.mysql.jdbc.exceptions.MySQLTimeoutException;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;
import com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException;

import indi.zjh.dp.cache.ObjectCache;
import indi.zjh.dp.db.Configuration;
import indi.zjh.dp.db.DataSource;
import indi.zjh.dp.db.Session;
import indi.zjh.dp.db.TableRepository;
import indi.zjh.dp.error.DatabaseUnwritableException;
import indi.zjh.dp.error.DeleteObjectNotAllowedException;
import indi.zjh.dp.error.NoSuchObjectException;
import indi.zjh.dp.error.ObjectAlreadyContainedException;
import indi.zjh.dp.error.ObjectIdInvalidException;
import indi.zjh.dp.error.ParameterNotMatchException;
import indi.zjh.dp.error.UnsuportedFieldException;
import indi.zjh.dp.type.GTrace;
import indi.zjh.dp.type.String128;
import indi.zjh.dp.type.String256;
import indi.zjh.dp.type.String64;
import indi.zjh.dp.type.Text;
import jdk.nashorn.internal.runtime.regexp.joni.Config;

public class BusinessProcess {
	
	private static Logger logger = Logger.getLogger(BusinessProcess.class);
	
	public String preclassname = null;
	public String curclassname = null;
	public Business obj = null;
	public int type = RelationStrategy.INIT;
	
	
	
	
	public int process(Session sess, Business obj) throws UnsuportedFieldException, DocumentException, Exception
	{
		int opttype = -1;
		String clsname = null;
		if(this.curclassname == null)
		{
			clsname = obj.getClass().getName();
		}
		else
		{
			clsname = this.curclassname;
		}
		
		RelationClass rc = Configuration.getInstance().getVersion().getRelationClass(clsname);
		//obj.printIds();
		
		long id = obj.getSpecId(clsname);
		String sql = null;
		// 添加新记录
		if(id == 0)
		{
			sql = TableRepository.getInstance().getInsertSql(clsname);
			Object[] values = this.getObjectValue(obj, false);
			long newids[] = sess.insert(sql, values);

			obj.saveId(clsname, newids[0]);
			// 只插入子类的数据
			if(this.preclassname == null)
			{
				//DataSource.add(sess, obj, DataSource.CREATE);
				opttype = DataSource.CREATE;
			}
			// 处理关系
			if(this.type == RelationStrategy.EXTEND)
			{
				this.processRelation(sess, clsname, this.preclassname, newids[0], this.obj.getSpecId(this.preclassname), RelationStrategy.EXTEND, true);
			}
			else if(this.type == RelationStrategy.COMPOSITION)
			{
				this.processRelation(sess, clsname, this.preclassname, newids[0], this.obj.getSpecId(this.preclassname), RelationStrategy.COMPOSITION, true);
			}
			else if(this.type == RelationStrategy.AGGREGATION)
			{
				this.processRelation(sess, clsname, this.preclassname, newids[0], this.obj.getSpecId(this.preclassname), RelationStrategy.AGGREGATION, true);
			}
			
			// 处理继承类
			if(rc.parentClass != null)
			{
				BusinessProcess p = new BusinessProcess();
				p.curclassname = rc.parentClass.getName();
				p.preclassname = clsname;
				p.obj = obj;
				p.type = RelationStrategy.EXTEND;
				p.process(sess, obj);
			}
			// 处理组合类
			if(rc.containingField.size() > 0)
			{
				Iterator<Map.Entry<String, Field>> iter = rc.containingField.entrySet().iterator();
				while(iter.hasNext())
				{
					Map.Entry<String, Field> entry = iter.next();
					//String containFieldName = entry.getKey();
					Field containField = entry.getValue();
					String subclsname = containField.getType().getName();
					Business cobj = (Business)containField.get(obj);
					BusinessProcess p = new BusinessProcess();
					p.preclassname = clsname;
					p.obj = obj;
					p.type = RelationStrategy.COMPOSITION;
					p.process(sess, cobj);
					if(cobj.getSpecId(subclsname) > 0)
					{
						long[] existid = this.getRelationIds(sess, subclsname, clsname, cobj.getSpecId(subclsname), RelationStrategy.COMPOSITION);
						if(existid.length > 0)
						{
							if(!(existid.length == 1 && existid[0] == obj.getSpecId(clsname)))
								throw new ObjectAlreadyContainedException();
						}
						this.processRelation(sess, clsname, subclsname, obj.getSpecId(clsname), cobj.getSpecId(subclsname), RelationStrategy.COMPOSITION, true);
					}
				}
			}
			// 处理聚合类
			if(rc.aggregationFieldMap.size() > 0)
			{
				Iterator<Map.Entry<String, Field>> iter = rc.aggregationFieldMap2.entrySet().iterator();
				while(iter.hasNext())
				{
					Map.Entry<String, Field> entry = iter.next();
					String aggFieldName = entry.getKey();
					Field aggField = entry.getValue();
					
					GTrace<Business> container = (GTrace<Business>)aggField.get(obj);
					String subclsname = rc.aggregationFieldMap.get(aggFieldName);
					
					Iterator<Business> iiter = container.getFinalAddSet().iterator();
					while(iiter.hasNext())
					{
						Business aobj = (Business)iiter.next();
						BusinessProcess p = new BusinessProcess();
						p.preclassname = clsname;
						p.obj = obj;
						p.type = RelationStrategy.AGGREGATION;
						p.process(sess, aobj);

						if(aobj.getSpecId(subclsname) > 0)
						{
							this.processRelation(sess, clsname, subclsname, obj.getSpecId(clsname), aobj.getSpecId(subclsname), RelationStrategy.AGGREGATION, true);
						}
					}
					
					// 不用处理被最终移除聚合对象
					// 恢复跟踪标记
					container.clearFinalSet();
					
					
				}
			}
			// 处理关联类
			if(rc.associationFieldSet.size() > 0)
			{
				Iterator<Field> iter = rc.associationFieldSet.iterator();
				while(iter.hasNext())
				{
					Field assField = iter.next();
					Relation rel = (Relation)assField.get(obj);
					GTrace<Long> container = (GTrace<Long>)rel.getIdSet();
					Iterator<Long> adds = container.getFinalAddSet().iterator();
					while(adds.hasNext())
					{
						long bid = adds.next().longValue();
						//this.processRelation(sess, clsname, rel.getRelationClassName(), newids[0], bid, RelationStrategy.ASSOCIATION, true);
						// 支持单向关联
						this.processRelation(sess, clsname, rel.getRelationClassName(), newids[0], bid, RelationStrategy.ASSOCIATION, true, rel.getLinkType() == Relation.MUTUAL);
					}
					
					Iterator<Long> dels = container.getFinalRemoveSet().iterator();
					while(dels.hasNext())
					{
						long bid = dels.next().longValue();
						this.processRelation(sess, clsname, rel.getRelationClassName(), newids[0], bid, RelationStrategy.ASSOCIATION, false);
					}
					container.clearFinalSet();
				}
			}
		}
		else
		{
			// 删除
			if(obj.isDelete())
			{
				
				// 如果对象被包含
				if(this.type == RelationStrategy.INIT && obj.isContained(sess))
				{
					throw new DeleteObjectNotAllowedException();
				}
				// 如果删除的不是继承树的叶子对象
				if(this.type == RelationStrategy.INIT && rc.directSubClass.size() > 0)
				{
					boolean hasSubObject = false;
					Iterator<RelationClass> niter = rc.directSubClass.iterator();
					while(niter.hasNext())
					{
						RelationClass subrc = niter.next();
						long subid = this.getRelationId(sess, clsname, subrc.getName(), obj.getSpecId(clsname), RelationStrategy.EXTEND);
						if(subid > 0)
						{
							hasSubObject = true;
							Business subobj = (Business)sess.getById(subrc.getClazz(), subid);
							subobj.delete();
							BusinessProcess sp = new BusinessProcess();
							sp.type = RelationStrategy.INIT;
							sp.process(sess, subobj);
						}
					}
					if(hasSubObject)
						return opttype;
				}
				
				sql = TableRepository.getInstance().getUpdateSql(clsname);
				Object[] values = this.getObjectValue(obj, true);
				int affected = sess.execute(sql, values);
				
				if(this.preclassname == null)
				{
					//DataSource.add(sess, obj, DataSource.DELETE);
					opttype = DataSource.DELETE;
				}
				
				// 删除缓存
				if(affected > 0)
				{
					ObjectCache.getInstance().flushObject(obj);
				}
				
				// 处理继承类
				if(rc.parentClass != null)
				{
					BusinessProcess p = new BusinessProcess();
					p.curclassname = rc.parentClass.getName();
					p.preclassname = clsname;
					p.obj = obj;
					p.type = RelationStrategy.EXTEND;
					p.process(sess, obj);
					
				}
				// 处理组合类
				if(rc.containingField.size() > 0)
				{
					Iterator<Map.Entry<String, Field>> iter = rc.containingField.entrySet().iterator();
					while(iter.hasNext())
					{
						Map.Entry<String, Field> entry = iter.next();
						//String containFieldName = entry.getKey();
						Field containField = entry.getValue();
						Business cobj = (Business)containField.get(obj);
						
						// 同时删除包含的对象
						cobj.delete();
						BusinessProcess p = new BusinessProcess();
						p.preclassname = clsname;
						p.obj = obj;
						p.type = RelationStrategy.COMPOSITION;
						p.process(sess, cobj);
					}
				}
				// 处理聚合类
				if(rc.aggregationFieldMap.size() > 0)
				{
					Iterator<Map.Entry<String, Field>> iter = rc.aggregationFieldMap2.entrySet().iterator();
					while(iter.hasNext())
					{
						Map.Entry<String, Field> entry = iter.next();
						String aggFieldName = entry.getKey();
						Field aggField = entry.getValue();
						
						String subclsname = rc.aggregationFieldMap.get(aggFieldName);
						Class<?> acls = Configuration.getInstance().getVersion().getRelationClass(subclsname).getClazz();
						
						GTrace<Business> container = (GTrace<Business>)aggField.get(obj);
						Iterator<Business> iiter = container.getFinalAddSet().iterator();
						boolean hasRelationUpdate = false;
						while(iiter.hasNext())
						{
							Business aobj = (Business)iiter.next();
							// 递归处理聚合对象
							BusinessProcess p = new BusinessProcess();
							p.preclassname = clsname;
							p.obj = obj;
							p.type = RelationStrategy.AGGREGATION;
							p.process(sess, aobj);
							
							// 处理关系
							if(aobj.getSpecId(subclsname) > 0)
							{
								this.processRelation(sess, clsname, subclsname, obj.getSpecId(clsname), aobj.getSpecId(subclsname), RelationStrategy.AGGREGATION, true);
								hasRelationUpdate = true;
							}
						}
						iiter = container.getFinalRemoveSet().iterator();
						while(iiter.hasNext())
						{
							Business aobj = (Business)iiter.next();
							// 处理关系
							if(aobj.getSpecId(subclsname) > 0)
							{
								this.processRelation(sess, clsname, subclsname, obj.getSpecId(clsname), aobj.getSpecId(subclsname), RelationStrategy.AGGREGATION, false);
								hasRelationUpdate = true;
							}
						}
						// 不用处理被最终移除聚合对象
						// 恢复跟踪标记
						container.clearFinalSet();
						
						if(hasRelationUpdate)
						{
							ObjectCache.getInstance().flushObject(obj);
						}
					}
				}
				// 处理关联类
				if(rc.associationFieldSet.size() > 0)
				{
					Iterator<Field> iter = rc.associationFieldSet.iterator();
					while(iter.hasNext())
					{
						Field assField = iter.next();
						Relation rel = (Relation)assField.get(obj);
						GTrace<Long> container = (GTrace<Long>)rel.getIdSet();
						Iterator<Long> adds = container.getFinalAddSet().iterator();
						boolean hasRelationUpdate = false;

						while(adds.hasNext())
						{
							long bid = adds.next().longValue();
							this.processRelation(sess, clsname, rel.getRelationClassName(), obj.getSpecId(clsname), bid, RelationStrategy.ASSOCIATION, true);
							ObjectCache.getInstance().flushObject(obj);
							hasRelationUpdate = true;
							ObjectCache.getInstance().flushObjectById(rel.getRelationClassName(), bid);
						}
						
						Iterator<Long> dels = container.getFinalRemoveSet().iterator();
						while(dels.hasNext())
						{
							long bid = dels.next().longValue();
							this.processRelation(sess, clsname, rel.getRelationClassName(), obj.getSpecId(clsname), bid, RelationStrategy.ASSOCIATION, false);
							hasRelationUpdate = true;
							ObjectCache.getInstance().flushObjectById(rel.getRelationClassName(), bid);
						}
						container.clearFinalSet();
						
						if(hasRelationUpdate)
						{
							ObjectCache.getInstance().flushObject(obj);
						}
					}
				}
			}
			// 更新
			else
			{
				int affected = 0;
				if(obj.isModified())
				{
				
					sql = TableRepository.getInstance().getUpdateSql(clsname);
					Object[] values = this.getObjectValue(obj, true);
					affected = sess.execute(sql, values);
					
					if(this.preclassname == null)
					{
						//DataSource.add(sess, obj, DataSource.UPDATE);
						opttype = DataSource.UPDATE;
					}
				}
				else
				{
					opttype = -1;
				}
				
				// 删除缓存
				if(affected > 0)
				{
					ObjectCache.getInstance().flushObject(obj);
				}
				
				// 处理继承类
				if(rc.parentClass != null)
				{
					BusinessProcess p = new BusinessProcess();
					p.curclassname = rc.parentClass.getName();
					p.preclassname = clsname;
					p.obj = obj;
					p.type = RelationStrategy.EXTEND;
					p.process(sess, obj);
				}
				// 处理组合类
				if(rc.containingField.size() > 0)
				{
					Iterator<Map.Entry<String, Field>> iter = rc.containingField.entrySet().iterator();
					while(iter.hasNext())
					{
						Map.Entry<String, Field> entry = iter.next();
						//String containFieldName = entry.getKey();
						Field containField = entry.getValue();
						Business cobj = (Business)containField.get(obj);
						BusinessProcess p = new BusinessProcess();
						p.preclassname = clsname;
						p.obj = obj;
						p.type = RelationStrategy.COMPOSITION;
						p.process(sess, cobj);
					}
				}
				// 处理聚合类
				if(rc.aggregationFieldMap.size() > 0)
				{
					Iterator<Map.Entry<String, Field>> iter = rc.aggregationFieldMap2.entrySet().iterator();
					while(iter.hasNext())
					{
						Map.Entry<String, Field> entry = iter.next();
						String aggFieldName = entry.getKey();
						Field aggField = entry.getValue();
						
						String subclsname = rc.aggregationFieldMap.get(aggFieldName);
						Class<?> acls = Configuration.getInstance().getVersion().getRelationClass(subclsname).getClazz();
						
						GTrace<Business> container = (GTrace<Business>)aggField.get(obj);
						Iterator<Business> iiter = container.getFinalAddSet().iterator();
						
						boolean hasRelationUpdate = false;
						while(iiter.hasNext())
						{
							Business aobj = (Business)iiter.next();
							// 递归处理聚合对象
							BusinessProcess p = new BusinessProcess();
							p.preclassname = clsname;
							p.obj = obj;
							p.type = RelationStrategy.AGGREGATION;
							p.process(sess, aobj);

							// 处理关系
							if(aobj.getSpecId(subclsname) > 0)
							{
								this.processRelation(sess, clsname, subclsname, obj.getSpecId(clsname), aobj.getSpecId(subclsname), RelationStrategy.AGGREGATION, true);
								hasRelationUpdate = true;
							}
						}
						iiter = container.getFinalRemoveSet().iterator();
						while(iiter.hasNext())
						{
							Business aobj = (Business)iiter.next();
							// 处理关系
							if(aobj.getSpecId(subclsname) > 0)
							{
								this.processRelation(sess, clsname, subclsname, obj.getSpecId(clsname), aobj.getSpecId(subclsname), RelationStrategy.AGGREGATION, false);
								hasRelationUpdate = true;
							}
						}
						// 不用处理被最终移除聚合对象
						// 恢复跟踪标记
						container.clearFinalSet();
						
						if(hasRelationUpdate)
						{
							ObjectCache.getInstance().flushObject(obj);
						}
					}
				}
				// 处理关联类
				if(rc.associationFieldSet.size() > 0)
				{
					Iterator<Field> iter = rc.associationFieldSet.iterator();
					while(iter.hasNext())
					{
						Field assField = iter.next();
						Relation rel = (Relation)assField.get(obj);
						GTrace<Long> container = (GTrace<Long>)rel.getIdSet();
						Iterator<Long> adds = container.getFinalAddSet().iterator();
						boolean hasRelationUpdate = false;
						while(adds.hasNext())
						{
							long bid = adds.next().longValue();
							this.processRelation(sess, clsname, rel.getRelationClassName(), obj.getSpecId(clsname), bid, RelationStrategy.ASSOCIATION, true, rel.getLinkType() == Relation.MUTUAL);
							hasRelationUpdate = true;
							ObjectCache.getInstance().flushObjectById(rel.getRelationClassName(), bid);
						}
						
						Iterator<Long> dels = container.getFinalRemoveSet().iterator();
						while(dels.hasNext())
						{
							long bid = dels.next().longValue();
							this.processRelation(sess, clsname, rel.getRelationClassName(), obj.getSpecId(clsname), bid, RelationStrategy.ASSOCIATION, false);
							hasRelationUpdate = true;
							ObjectCache.getInstance().flushObjectById(rel.getRelationClassName(), bid);
						}
						container.clearFinalSet();
						
						if(hasRelationUpdate)
						{
							ObjectCache.getInstance().flushObject(obj);
						}
					}
				}

			}
		}
		
		return opttype;
	}
	

	public void getById(Session sess, Class<?> cls, long id, Business obj) throws Exception
	{
		if(id == 0)
		{
			throw new ObjectIdInvalidException();
		}
		
		String clsname = null;
		if(this.curclassname == null)
		{
			clsname = obj.getClass().getName();
			this.curclassname = clsname;
		}
		else
		{
			clsname = this.curclassname;
		}
		
		RelationClass rc = Configuration.getInstance().getVersion().getRelationClass(clsname);
		String sql = null;
		if(this.type != RelationStrategy.EXTEND)
		{
			sql = TableRepository.getInstance().getSelectSql(clsname);
		}
		else
		{
			sql = TableRepository.getInstance().getSelectExSql(clsname);
		}
		List<Map<String, Object>> rows = sess.query(sql, new Object[]{id});
		if(rows.size() == 0)
		{
			throw new NoSuchObjectException();
		}

		// 保存数据
		Map<String, Object> row = rows.get(0);
		Iterator<Map.Entry<String, Object>> iter = row.entrySet().iterator();
		while(iter.hasNext())
		{
			Map.Entry<String, Object> entry = iter.next();
			String fieldName = entry.getKey();
			Object fieldValue = entry.getValue();
			Field field = TableRepository.getInstance().getFieldByName(clsname, fieldName);
			this.setFieldValue(obj, field, fieldValue);
		}
		
		// 处理继承类
		if(rc.parentClass != null)
		{
			BusinessProcess p = new BusinessProcess();
			p.curclassname = rc.parentClass.getName();
			p.preclassname = clsname;
			p.obj = obj;
			p.type = RelationStrategy.EXTEND;
			Class<?> subcls = rc.parentClass.getClazz();
			long bid = this.getRelationId(sess, clsname, p.curclassname, obj.getSpecId(clsname), RelationStrategy.EXTEND);
			if(bid == 0)
			{
				throw new NoSuchObjectException();
			}
			p.getById(sess, subcls, bid, obj);
		}
		// 处理组合类
		if(rc.containingField.size() > 0)
		{
			Iterator<Map.Entry<String, Field>> niter = rc.containingField.entrySet().iterator();
			while(niter.hasNext())
			{
				Map.Entry<String, Field> entry = niter.next();
				//String containFieldName = entry.getKey();
				Field containField = entry.getValue();
				Business cobj = (Business)containField.get(obj);
				Class<?> ccls = containField.getDeclaringClass();
				long bid = this.getRelationId(sess, clsname, cobj.getClass().getName(), obj.getSpecId(clsname), RelationStrategy.COMPOSITION);
				if(bid == 0)
				{
					throw new NoSuchObjectException();
				}
				BusinessProcess p = new BusinessProcess();
				p.preclassname = clsname;
				p.obj = obj;
				p.type = RelationStrategy.COMPOSITION;
				p.getById(sess, ccls, bid, cobj);
			}
		}
		// 处理聚合类
		if(rc.aggregationFieldMap.size() > 0)
		{
			Iterator<Map.Entry<String, Field>> niter = rc.aggregationFieldMap2.entrySet().iterator();
			while(niter.hasNext())
			{
				Map.Entry<String, Field> entry = niter.next();
				String aggFieldName = entry.getKey();
				Field aggField = entry.getValue();
				String subclsname = rc.aggregationFieldMap.get(aggFieldName);
				Class<?> acls = Configuration.getInstance().getVersion().getRelationClass(subclsname).getClazz();
				Collection<Business> container = (Collection<Business>)aggField.get(obj);
				// 恢复跟踪标记
				GTrace<Business> gcontainer = (GTrace<Business>)container;
				gcontainer.clearFinalSet();
				
				long[] ids = this.getRelationIds(sess, clsname, subclsname, obj.getSpecId(clsname), RelationStrategy.AGGREGATION);
				for(int i = 0; i < ids.length; ++i)
				{
					Business aobj = (Business)acls.newInstance();
					aobj.saveId(acls.getName(), ids[i]);
					BusinessProcess p = new BusinessProcess();
					p.curclassname = subclsname;
					p.preclassname = clsname;
					p.obj = obj;
					p.type = RelationStrategy.AGGREGATION;
					p.getById(sess, acls, ids[i], aobj);
					container.add(aobj);
				}
				// 不用处理被最终移除聚合对象
				
			}
		}
		// 处理关联类
		if(rc.associationFieldSet.size() > 0)
		{
			Iterator<Field> niter = rc.associationFieldSet.iterator();
			while(niter.hasNext())
			{
				Field assField = niter.next();
				Relation rel = (Relation)assField.get(obj);
				
				
				
				long[] ids = this.getRelationIds(sess, clsname, rel.getRelationClassName(), obj.getSpecId(clsname), RelationStrategy.ASSOCIATION);
				for(int i = 0; i < ids.length; ++i)
				{
					rel.add(ids[i]);
				}
				
				GTrace<Long> container = (GTrace<Long>)rel.getIdSet();
				container.clearFinalSet();
			}
		}
	}
	
	
	protected void processRelation(Session sess, String clsa, String clsb, long aid, long bid, int type, boolean isInsert) throws MysqlDataTruncation, MySQLSyntaxErrorException, MySQLIntegrityConstraintViolationException, MySQLTimeoutException, ParameterNotMatchException, DatabaseUnwritableException, SQLException
	{
		String sql = null;
		if(isInsert)
		{
			sql = TableRepository.getInstance().getRelationInsertSql(clsa, clsb);
			sess.insert(sql, new Object[]{type, aid, bid}, true);
			sql = TableRepository.getInstance().getRelationInsertSql(clsb, clsa);
			sess.insert(sql, new Object[]{type, bid, aid}, true);
		}
		else
		{
			sql = TableRepository.getInstance().getRelationDeleteSql(clsa, clsb);
			sess.execute(sql, new Object[]{type, aid, bid});
			sql = TableRepository.getInstance().getRelationDeleteSql(clsb, clsa);
			sess.execute(sql, new Object[]{type, bid, aid});
		}
	}
	
	protected void processRelation(Session sess, String clsa, String clsb, long aid, long bid, int type, boolean isInsert, boolean isMutual) throws MysqlDataTruncation, MySQLSyntaxErrorException, MySQLIntegrityConstraintViolationException, MySQLTimeoutException, ParameterNotMatchException, DatabaseUnwritableException, SQLException
	{
		String sql = null;
		if(isInsert)
		{
			sql = TableRepository.getInstance().getRelationInsertSql(clsa, clsb);
			sess.insert(sql, new Object[]{type, aid, bid}, true);
			if(isMutual)
			{
				sql = TableRepository.getInstance().getRelationInsertSql(clsb, clsa);
				sess.insert(sql, new Object[]{type, bid, aid}, true);
			}
		}
		else
		{
			sql = TableRepository.getInstance().getRelationDeleteSql(clsa, clsb);
			sess.execute(sql, new Object[]{type, aid, bid});
			sql = TableRepository.getInstance().getRelationDeleteSql(clsb, clsa);
			sess.execute(sql, new Object[]{type, bid, aid});
		}
	}
	
	protected Object[] getObjectValue(Business obj, boolean isUpdate) throws IllegalArgumentException, IllegalAccessException
	{
		String clsname = null;
		if(this.curclassname == null)
		{
			clsname = obj.getClass().getName();
		}
		else
		{
			clsname = this.curclassname;
		}
		
		ArrayList<Field> fields = TableRepository.getInstance().getFields(clsname);
		
		int len = fields.size();
		
		Object[] values = null;
		if(isUpdate)
			values = new Object[len+2];
		else
			values = new Object[len];
		
		long thisid = 0;
		long thisv = 0;
		int i;
		for(i = 0; i < len; ++i)
		{
			Field f = fields.get(i);
			if(f.getName().equals("_class"))
			{
				values[i] = clsname;
			}
			else if(f.getName().equals("_id"))
			{
				thisid = obj.getSpecId(clsname);
				values[i] = thisid;
				if(thisid == 0 && !Configuration.isMysql())
				{
					values[i] = "NULL";
				}
				
			}
			else if(f.getName().equals("_v"))
			{
				thisv = obj.getSpecVersion(clsname);
				// 乐观锁版本号自增
				if(isUpdate)
					values[i] = thisv + 1;
				else
					values[i] = thisv;
			}
			else if(f.getType().getName().equals("indi.zjh.dp.type.Text"))
			{
				Text text = (Text)f.get(obj);
				values[i] = text.string;
			}
			else if(f.getType().getName().equals("indi.zjh.dp.type.String64"))
			{
				String64 str = (String64)f.get(obj);
				values[i] = str.string;
			}
			else if(f.getType().getName().equals("indi.zjh.dp.type.String128"))
			{
				String128 str = (String128)f.get(obj);
				values[i] = str.string;
			}
			else if(f.getType().getName().equals("indi.zjh.dp.type.String256"))
			{
				String256 str = (String256)f.get(obj);
				values[i] = str.string;
			}
			else
			{
				values[i] = f.get(obj);
			}
		}
		
		if(isUpdate)
		{
			values[i++] = thisid;
			values[i++] = thisv;
		}
		
		return values;
	}
	
	protected long getRelationId(Session sess, String clsa, String clsb, long aid, int type) throws Exception
	{
		String sql = TableRepository.getInstance().getRelationSelectSql(clsa, clsb);
		List<Map<String, Object>> rows = sess.query(sql, new Object[]{type, aid});
		if(rows.size() == 0)
			return 0;
		
		if(Configuration.isMysql())
		{
			Long lo = (Long)rows.get(0).get("bid");
			return lo.longValue();
		}
		else
		{
			Integer lo = (Integer)rows.get(0).get("bid");
			return lo.intValue();
		}
	}
	
	protected long[] getRelationIds(Session sess, String clsa, String clsb, long aid, int type) throws Exception
	{
		String sql = TableRepository.getInstance().getRelationSelectSql(clsa, clsb);
		List<Map<String, Object>> rows = sess.query(sql, new Object[]{type, aid});
		
		int len = rows.size();
		long[] ids = new long[len];
		for(int i = 0; i < len; ++i)
		{
			//Long lo = (Long)rows.get(i).get("bid");
			//ids[i] = lo.longValue();
			Number lo = (Number)rows.get(i).get("bid");
			ids[i] = lo.longValue();
		}
		return ids;
	}
	
	
	
	public void setFieldValue(Business obj, Field f, Object v) throws IllegalArgumentException, IllegalAccessException
	{
		if(f.getType().getName().equals("double"))
		{
			if(Configuration.isMysql())
			{
				java.math.BigDecimal dval = (java.math.BigDecimal)v;
				f.set(obj, dval.doubleValue());
			}
			else
			{
				if(v.getClass().getName().equals("java.lang.Double"))
				{
					Double dval = (Double)v;
					f.set(obj, dval.doubleValue());
				}
				else if(v.getClass().getName().equals("java.lang.Integer"))
				{
					Integer ival = (Integer)v;
					f.set(obj, ival.intValue());
				}
			}
		}
		else if(f.getType().getName().equals("indi.zjh.dp.type.Text"))
		{
			Text text = new Text();
			text.string = (String)v;
			f.set(obj, text);
		}
		else if(f.getType().getName().equals("indi.zjh.dp.type.String64"))
		{
			String64 text = new String64();
			text.string = (String)v;
			f.set(obj, text);
		}
		else if(f.getType().getName().equals("indi.zjh.dp.type.String128"))
		{
			String128 text = new String128();
			text.string = (String)v;
			f.set(obj, text);
		}
		else if(f.getType().getName().equals("indi.zjh.dp.type.String256"))
		{
			String256 text = new String256();
			text.string = (String)v;
			f.set(obj, text);
		}
		else if(f.getName().equals("_id"))
		{
			if(!Configuration.isMysql())
			{
				int id = (int)v; 
				obj.saveId(this.curclassname, id);
			}
			else
			{
				long id = (long)v;
				obj.saveId(this.curclassname, id);
			}
		}
		else if(f.getName().equals("_v"))
		{
			if(!Configuration.isMysql())
			{
				int ver = (int)v;
				obj.saveVersion(this.curclassname, ver);
			}
			else
			{
				long ver = (long)v;
				obj.saveVersion(this.curclassname, ver);
			}
		}
		else if(f.getType().getName().equals("boolean"))
		{
			f.setBoolean(obj, v.toString().equals("1") ? true : false);
		}
		else if(f.getType().getName().equals("java.util.Date"))
		{
			if(!Configuration.isMysql())
				f.set(obj, new Date(Long.parseLong(v.toString())));
		}
		else
		{
			//System.out.println(f.getType().getName());
			f.set(obj, v);
		}
	}
}
